package cn.jiadakeji.parent.service.impl;

import cn.jiadakeji.parent.common.constant.RedisPrefixConstants;
import cn.jiadakeji.parent.common.exception.ServiceException;
import cn.jiadakeji.parent.common.util.DateUtils;
import cn.jiadakeji.parent.common.util.SecurityUtils;
import cn.jiadakeji.parent.domain.*;
import cn.jiadakeji.parent.dto.*;
import cn.jiadakeji.parent.mapper.TermCourseMapper;
import cn.jiadakeji.parent.mapper.TermCourseStudentMapper;
import cn.jiadakeji.parent.service.*;
import cn.jiadakeji.parent.vo.TermTimeCourseLeaveVo;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import sun.misc.ObjectInputFilter;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author heyanfeng
 * @create 2022-03-11 11:00
 */
@Service
public class TermCourseServiceImpl extends ServiceImpl<TermCourseMapper, TermCourse> implements TermCourseService {

    @Autowired
    private TermCourseStudentService courseStudentService;

    @Autowired
    private TermCourseStudentMapper courseStudentMapper;

    @Autowired
    private SchoolService schoolService;

    @Autowired
    private StudentService studentService;

    @Autowired
    private SchoolClassService classService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private TermTimeCourseService timeCourseService;

    @Autowired
    private TermTimeCourseLeaveService levelService;


    /**
     * 获取学生班课信息
     *
     * @return
     */
    @Override
    public MyTermCourseDTO getTerCourse(String studentId) {
        String data = redisTemplate.opsForValue().get(RedisPrefixConstants.STUDENT_COURSE_PREFIX + studentId);
        if (data != null) {
            return JSON.parseObject(data, MyTermCourseDTO.class);
        } else {
            // 1,根据studentId查找学生
            Student student = studentService.getById(studentId);
            // 2,查找班级信息
            SchoolClass schoolClass = classService.getById(student.getSchoolClassId());
            // 3,查询学校信息
            School school = schoolService.getById(schoolClass.getSchoolId());
            // 4,查询班课信息，当前学生的班课
            // 拿着studentId查找term_course_student表，得到termCourseId
            List<String> termCourseIds = courseStudentMapper.getTermCourseId(student.getId());
            List<TermCourseDTO> termCourseDTOList = null;
            if (termCourseIds != null && !ObjectUtils.isEmpty(termCourseIds)) {
                List<TermCourse> termCourses = baseMapper.selectBatchIds(termCourseIds);
                // 转换类型
                termCourseDTOList = termCourses.stream().map(course -> {
                    TermCourseDTO termCourseDTO = new TermCourseDTO();
                    BeanUtils.copyProperties(course, termCourseDTO);
                    // 设置图片
                    termCourseDTO.setPictures(course.getPicture());
                    // 设置学校信息
                    termCourseDTO.setSchoolName(school.getName());
                    termCourseDTO.setSchoolAddress(school.getAddress());
                    return termCourseDTO;
                }).collect(Collectors.toList());
            }
            // 设置信息
            MyTermCourseDTO myTermCourseDTO = new MyTermCourseDTO();
            myTermCourseDTO.setStudentName(student.getStudentName());
            myTermCourseDTO.setSchoolClassName(schoolClass.getClassName());
            myTermCourseDTO.setSchoolName(school.getName());
            myTermCourseDTO.setTermCourseDTOList(termCourseDTOList);
            String jsonString = JSON.toJSONString(myTermCourseDTO);
            // 存放7天
            redisTemplate.opsForValue().set(RedisPrefixConstants.STUDENT_COURSE_PREFIX + studentId, jsonString, 7, TimeUnit.DAYS);
            return myTermCourseDTO;
        }
    }

    /**
     * 获取班课详细信息
     */
    @Override
    public TermCourseDTO getTermDetail(String courseId) {
        String data = redisTemplate.opsForValue().get(RedisPrefixConstants.COURSE_DETAIL_PREFIX + courseId);
        if (data != null) {
            return JSON.parseObject(data, TermCourseDTO.class);
        } else {
            // 获取班课信息
            TermCourse termCourse = baseMapper.selectById(courseId);
            // 类型转换
            TermCourseDTO termCourseDTO = new TermCourseDTO();
            BeanUtils.copyProperties(termCourse, termCourseDTO);
            // 设置图片
            termCourseDTO.setPictures(termCourse.getPicture());
            // 设置学校信息
            School school = schoolService.getById(termCourse.getSchoolId());
            termCourseDTO.setSchoolName(school.getName());
            termCourseDTO.setSchoolAddress(school.getAddress());
            String jsonString = JSON.toJSONString(termCourseDTO);
            redisTemplate.opsForValue().set(RedisPrefixConstants.COURSE_DETAIL_PREFIX + courseId, jsonString, 7, TimeUnit.DAYS);
            return termCourseDTO;
        }

    }

    /**
     * 学生请假
     */
    @Transactional
    @Override
    public Boolean toLeave(String courseId, TermTimeCourseLeaveVo courseLeaveVo) {
        //// 获取当前时间
        //Date nowData = new Date();
        // 获取下次的上课时间
        Date courseBeginTime = courseLeaveVo.getCourseNextTimeDTO().getBeginTime();
        // 添加请假信息,判断请假时间是否合理
        // 计算分钟差
        long diff = timeDifference(courseBeginTime, DateUtils.getNowDate());
        // 时间差小于5分钟或者早于一天都视为请假失败
        if (diff < 5 || diff > 1440) {
            throw new ServiceException("请假时间错误，请假失败");
        } else {
            TermTimeCourseLeave termTimeCourseLevel = new TermTimeCourseLeave();
            BeanUtils.copyProperties(courseLeaveVo, termTimeCourseLevel);
            CustomerJwtDTO loginUser = SecurityUtils.getLoginUser();
            termTimeCourseLevel.setCreateBy(loginUser.getId());
            // 设置请假开始时间,比上课时间提前10分钟
            //courseBeginTime.setMinutes(courseBeginTime.getMinutes() - 10);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(courseBeginTime);
            calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) - 10);
            termTimeCourseLevel.setLeaveBeginDate(calendar.getTime());
            // 请假结束时间为上课结束时间
            termTimeCourseLevel.setLeaveEndDate(courseLeaveVo.getCourseNextTimeDTO().getEndTime());
            levelService.save(termTimeCourseLevel);
            return true;
        }
    }

    /**
     * 获取下一次上课时间
     *
     * @return
     */
    @Override
    public CourseNextTimeDTO leaveTime(String courseId) {
        // 获取上一周的今天到上一周结束时，最近的一次课程
        TermTimeCourse timeCourse =  timeCourseService.getPreCourseTime(courseId);
        // 为null说明本周的课已经上完或者课程已经结束
        if (timeCourse == null){
            throw new ServiceException("本周没有课程安排");
        }
        CourseNextTimeDTO courseNextTimeDTO = new CourseNextTimeDTO();
        BeanUtils.copyProperties(timeCourse,courseNextTimeDTO);
        return courseNextTimeDTO;
    }

    /**
     * 计算时间差
     *
     * @param beginTime      课程开始时间
     * @param leaveBeginTime 请假开始时间
     * @return
     */
    private long timeDifference(Date beginTime, Date leaveBeginTime) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        long diff = beginTime.getTime() - leaveBeginTime.getTime();
        // 计算差多少分钟
        return diff % nd % nh / nm;

    }

}
